/**
 * 
 */
package com.alstudio.module.xmpp.protocol.xmpp;

import java.util.ArrayList;

import android.os.Handler;
import android.os.Message;

import com.alstudio.app.ALLocalEnv;
import com.alstudio.event.ALEventDeliver;
import com.alstudio.module.xmpp.protocol.xmpp.data.ALXmppConnectionState;
import com.alstudio.module.xmpp.protocol.xmpp.data.ALXmppEventType;
import com.alstudio.module.xmpp.protocol.xmpp.packact.ALMessage;
import com.alstudio.pojo.ALXmppEvent;
import com.alstudio.ui.base.BaseActivity;
import com.alstudio.utils.log.ALLog;
import com.alstudio.view.toast.MyToastUtil;

/**
 * 此类用于接收到网络事件后，查询xmpp消息接收队列，通过回调函数，通过Handler抛回主线程，采用事件通知的方式驱动UI做界面更新。
 * UI界面通过registerListener函数将本身注册到xmpp消息接收队列中，调用unRegisterListener将自身从xmpp消息接收队列
 * 移除。当事件到达时，通过Handler抛回主线程，循环通知所有注册监听消息的界面。
 * 
 * @author alonso lee
 * 
 */
public class ALXmppEventNotifyManager {

	/* xmpp消息接收队列,此列表保存需要接收xmpp 事件的界面 */
	private ArrayList<BaseActivity> listenerList;

	private final int NOTIFY_UI_XMPP_EVENT_OCCURED = 10086;

	private Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			switch (msg.what) {
			case NOTIFY_UI_XMPP_EVENT_OCCURED:

				ALXmppEvent data = (ALXmppEvent) msg.obj;
				if (data.getResponseCode() != 0
						&& ALLocalEnv.getLocalEnv().getVersionConfig()
								.isDebugVersion()) {
					MyToastUtil.getInstance().showCenterToastOnCenter(
							data.getType() + " 出現錯誤 " + data.getResponseCode());
				}
				ALEventDeliver.getDefaultAlEventDeliver().postALEvent(data);
				startNotifyUIListener(data);

				break;
			}
		}
	};

	/**
	 * 
	 * @return 获取当前连接状态的字符串描述
	 * @author alonso lee
	 */
	public static String connectionState2String(
			ALXmppConnectionState connectionState) {
		String state = "";

		switch (connectionState) {
		case XMPP_STATE_IDLE:
			state = "离线";
			break;
		case XMPP_STATE_CONNECTING_SOCKET:
			state = "正在连接socket...";
			break;
		case XMPP_STATE_SOCKET_CONNECTED:
			state = "socket 已连接";
			break;
		case XMPP_STATE_OPENNING_STREAM:
			state = "正在打开流";
			break;
		case XMPP_STATE_CHECKING_LOGIN_PROTOCOL:
			state = "开始验证账号...";
			break;
		case XMPP_STATE_CONNECTION_ESTABLISHED:
			state = "已登陆服务器";
			break;
		}

		return state;
	}

	/**
	 * 创建Notifier，初始化xmpp消息接收队列
	 * 
	 * @author alonso lee
	 */
	public ALXmppEventNotifyManager() {
		// 初始化xmpp消息接收队列
//		listenerList = new ArrayList<BaseActivity>();
	}

	/**
	 * 将指定界面增加到xmpp消息接收队列中
	 * 
	 * @param activity
	 *            加入到xmpp消息接收队列的界面对象
	 * @author alonso lee
	 */
	public void registerListener(BaseActivity activity) {
		// if (!listenerList.contains(activity)) {
		// ALLog.i("register Xmpp Event Listener for " + activity.activityName);
		// listenerList.add(activity);
		// }
	}

	/**
	 * 将指定界面从xmpp消息队列中移除
	 * 
	 * @param activity
	 *            需要从移除的界面
	 * @author alonso lee
	 */
	public void unRegisterListener(BaseActivity activity) {
		if (activity != null) {
			// if (listenerList.contains(activity)) {
			// ALLog.i("unregister Xmpp Event Listener for "
			// + activity.activityName);
			// listenerList.remove(activity);
			// }
		}
	}

	/**
	 * 根据不同的消息类型，调用不同的回调函数通知UI
	 * 
	 * @param type
	 *            消息类型
	 * @param data
	 *            回调数据
	 */
	public void notifyAllListener(ALXmppEvent data) {
		android.os.Message msg = mHandler
				.obtainMessage(NOTIFY_UI_XMPP_EVENT_OCCURED);
		msg.obj = data;
		mHandler.sendMessage(msg);
	}

	/**
	 * 获取注册到xmpp消息队列的界面列表
	 * 
	 * @return null 表示当前列表中没有任何界面
	 * @author alonso lee
	 */
	public ArrayList<BaseActivity> getALXmppEventListeners() {
//		if (listenerList.size() > 0) {
//			return this.listenerList;
//		}
		// 当前没有任何界面注册到队列中，直接返回null
		return null;
	}

	private void startNotifyUIListener(ALXmppEvent data) {
		switch (data.getType()) {
		case XMPP_CONNECTION_STATE_CHANGED_EVENT:
			notifyConnectionStateChange(data);
			break;
		case XMPP_CONNECTION_ESTABLISHED_EVENT:
			notifyConnectionEstablished(data);
			break;
		case XMPP_CONNECTION_LOST_EVENT:
			notifyConnectionLost(data);
			break;
		case XMPP_AUTH_FAILED_EVENT:
			notifyAuthFailed(data);
			break;
		case XMPP_LOGOUT_SUCCESS_EVENT:
			notifyLogoutEvent(data);
			break;
		case XMPP_IQ_PACKAGE_RECEIVE_EVENT:
			break;
		case XMPP_MESSAGE_PACKAGE_RECEIVE_EVENT:
			// 收到消息
			notifyReceiveNewMessage(data);
			break;
		case XMPP_PRESENCE_PACKAGE_RECEIVE_EVENT:
			break;
		case XMPP_MESSAGE_BACK_RECEIVE_EVENT:
			// 消息回执
			notifyReceiveMessageBack(data);
			break;

		/*********************** voip ***********************************/
		case XMPP_ACCEPT_INCOMMING_CALL_RESULT:
			notifyAcceptIncommingCall(data);
			break;
		case XMPP_CANCEL_CALL_RESULT:
			notifyCancelCall(data);
			break;
		case XMPP_HANDUP_CALL_RESULT:
			notifyHandupCall(data);
			break;
		case XMPP_MAKE_CALL_RESULT:
			notifyMakeCall(data);
			break;
		case XMPP_NEW_INCOMMING_CALL:
			break;
		case XMPP_REJECT_INCOMMING_CALL_RESULT:
			notifyRejectIncommingCall(data);
			break;
		/*********************** voip ***********************************/
		default:
			break;
		}
	}

	private void notifyConnectionStateChange(ALXmppEvent data) {
		ArrayList<BaseActivity> mListeners = ALLocalEnv.mXmppEventNotifyManager
				.getALXmppEventListeners();
		if (mListeners != null) {
			for (BaseActivity b : mListeners) {
				if (b.isCallbackEnable()) {
					b.handleConnectStateChangedEvent(
							data.getNewConnectionState(),
							data.getLastConnectionState());
				} else {
					ALLog.i("ignore notify " + b.activityName);
				}
			}
		}
	}

	private void notifyConnectionEstablished(ALXmppEvent data) {
		ArrayList<BaseActivity> mListeners = ALLocalEnv.mXmppEventNotifyManager
				.getALXmppEventListeners();
		if (mListeners != null) {
			for (BaseActivity b : mListeners) {
				if (b.isCallbackEnable()) {
					b.handleLoginedEvent(data);
				} else {
					ALLog.i("ignore notify " + b.activityName);
				}
			}
		}
	}

	private void notifyConnectionLost(ALXmppEvent data) {
		ArrayList<BaseActivity> mListeners = ALLocalEnv.mXmppEventNotifyManager
				.getALXmppEventListeners();
		if (mListeners != null) {
			for (BaseActivity b : mListeners) {
				if (data.getErrorMessage().contains("conflict")) {
					if (b.isCallbackEnable()) {
						// 被踢下线了
						b.handleOnConflictEvent();
					} else {
						ALLog.i("ignore notify " + b.activityName);
					}
				} else {
					if (b.isCallbackEnable()) {
						b.handleConnectionLostEvent(data.getErrorMessage());
					} else {
						ALLog.i("ignore notify " + b.activityName);
					}
				}
			}
		}
	}

	private void notifyAuthFailed(ALXmppEvent data) {
		ArrayList<BaseActivity> mListeners = ALLocalEnv.mXmppEventNotifyManager
				.getALXmppEventListeners();
		if (mListeners != null) {
			for (BaseActivity b : mListeners) {
				if (b.isCallbackEnable()) {
					// 账号验证失败
					b.handleAuthFailedEvent(data.getErrorMessage());
				} else {
					ALLog.i("ignore notify " + b.activityName);
				}
			}
		}
	}

	private void notifyLogoutEvent(ALXmppEvent data) {
		ArrayList<BaseActivity> mListeners = ALLocalEnv.mXmppEventNotifyManager
				.getALXmppEventListeners();
		if (mListeners != null) {
			for (BaseActivity b : mListeners) {
				if (b.isCallbackEnable()) {
					// 注销成功
					b.handleLogoutEvent();
				} else {
					ALLog.i("ignore notify " + b.activityName);
				}
			}
		}
	}

	private void notifyReceiveNewMessage(ALXmppEvent data) {
		ArrayList<BaseActivity> mListeners = ALLocalEnv.mXmppEventNotifyManager
				.getALXmppEventListeners();
		if (mListeners != null) {
			for (BaseActivity b : mListeners) {
				if (b.isCallbackEnable()) {
					// 收到新消息
					switch (data.getMessage().getType()) {
					case ALMessage.NEW_INCOMMING_CALL:
						b.handleNewIncommingCallEvent(data.getMessage());
						break;
					case ALMessage.USER_ACCEPT_CALL:
						b.handleUserAcceptCallEvent(data.getMessage());
						break;
					case ALMessage.USER_HANDUP_CALL:
						b.handleUserHandupEvent(data.getMessage());
						break;
					case ALMessage.USER_REJECT_CALL:
						b.handleUserRejectCallEvent(data.getMessage());
						break;
					case ALMessage.USER_VOIP_ADDR_SET:
						b.handleUserVoipAddrSetEvent(data.getMessage());
						break;
					default:
						b.handleOnNewMessageArrivedEvent(data.getMessage());
						break;
					}
				} else {
					ALLog.i("ignore notify " + b.activityName);
				}
			}
		}
	}

	private void notifyReceiveMessageBack(ALXmppEvent data) {

		ArrayList<BaseActivity> mListeners = ALLocalEnv.mXmppEventNotifyManager
				.getALXmppEventListeners();
		if (mListeners != null) {
			for (BaseActivity b : mListeners) {
				if (b.isCallbackEnable()) {
					// 收到回执
					b.handleOnMessageReceiptEvent();
				} else {
					ALLog.i("ignore notify " + b.activityName);
				}
			}
		}
	}

	private void notifyAcceptIncommingCall(ALXmppEvent data) {
		ArrayList<BaseActivity> mListeners = ALLocalEnv.mXmppEventNotifyManager
				.getALXmppEventListeners();
		if (mListeners != null) {
			for (BaseActivity b : mListeners) {
				if (b.isCallbackEnable()) {
					//
					b.handleAcceptCallEvent(data);
				} else {
					ALLog.i("ignore notify " + b.activityName);
				}
			}
		}
	}

	private void notifyRejectIncommingCall(ALXmppEvent data) {
		ArrayList<BaseActivity> mListeners = ALLocalEnv.mXmppEventNotifyManager
				.getALXmppEventListeners();
		if (mListeners != null) {
			for (BaseActivity b : mListeners) {
				if (b.isCallbackEnable()) {
					//
					b.handleRejectCallEvent(data);
				} else {
					ALLog.i("ignore notify " + b.activityName);
				}
			}
		}
	}

	private void notifyHandupCall(ALXmppEvent data) {
		ArrayList<BaseActivity> mListeners = ALLocalEnv.mXmppEventNotifyManager
				.getALXmppEventListeners();
		if (mListeners != null) {
			for (BaseActivity b : mListeners) {
				if (b.isCallbackEnable()) {
					//
					b.handleHandupCallEvent(data);
				} else {
					ALLog.i("ignore notify " + b.activityName);
				}
			}
		}
	}

	private void notifyCancelCall(ALXmppEvent data) {
		ArrayList<BaseActivity> mListeners = ALLocalEnv.mXmppEventNotifyManager
				.getALXmppEventListeners();
		if (mListeners != null) {
			for (BaseActivity b : mListeners) {
				if (b.isCallbackEnable()) {
					//
					b.handleCancelCallEvent(data);
				} else {
					ALLog.i("ignore notify " + b.activityName);
				}
			}
		}
	}

	private void notifyMakeCall(ALXmppEvent data) {
		ArrayList<BaseActivity> mListeners = ALLocalEnv.mXmppEventNotifyManager
				.getALXmppEventListeners();
		if (mListeners != null) {
			for (BaseActivity b : mListeners) {
				if (b.isCallbackEnable()) {
					//
					b.handleMakeCallEvent(data);
				} else {
					ALLog.i("ignore notify " + b.activityName);
				}
			}
		}
	}

}
